use std::{thread, time::Duration};

use thirtyfour::prelude::*;

enum DataDone {
    // 结束当前页面抓取, 意味着拖拽新数据
    EndCurrent,
    // 结束所有页面抓取, 意味着退出抓取程序
    EndAll,
    // 没有什么事情, 继续下一个操作
    No,
}

struct ScrapyRecord {
    // 标记新页出现
    // 当新页被设置, 说明新数据出现, 我们需要进行额外的设置
    new_page: bool,
    // 记录每一个上次的数据
    // 用于去除重复的数据
    new_prev_data: String,
    // 记录新页的第一个数据
    prev_data: String,
    // 记录上一次刷新页的数据
    old_prev_data: String,
    // web 自动化驱动
    driver: WebDriver,
}

impl ScrapyRecord {
    fn new(d: WebDriver) -> Self {
        Self {
            new_page: false,
            new_prev_data: String::from("null"),
            prev_data: String::from("null"),
            old_prev_data: String::new(),
            driver: d,
        }
    }
}

// 一共六组数据:
// 1. hxc3-hxc3KlinePricePane-hover: 整体涨跌数据
// 2. hxc3-hxc3KlinePricePane-hover-ma: MACD 数据
// 3. hxc3-hxc3KlineVolPane-hover: 成交量
// 4. hxc3-TechMACDPane-hover: MACD 更新数据
// 5. hxc3-hxc3KlinePricePane-hover-time: 日期
// 6. hxc3-hxc3KlinePricePane-hover-price: 当日实际价值
async fn handle_data(record: &mut ScrapyRecord) -> WebDriverResult<DataDone> {
    let d = &record.driver;
    let five_raw = d
        .find(By::XPath(
            "//div[@class='hxc3-hxc3KlinePricePane-hover-time']",
        ))
        .await;
    if five_raw.is_err() {
        return Ok(DataDone::No);
    }

    let five = five_raw.ok().unwrap();
    let two = d
        .find(By::XPath(
            "//div[@class='hxc3-hxc3KlinePricePane-hover-ma']",
        ))
        .await?;
    let three = d
        .find(By::XPath("//div[@class='hxc3-hxc3KlineVolPane-hover']"))
        .await?;
    let four = d
        .find(By::XPath("//div[@class='hxc3-TechMACDPane-hover']"))
        .await?;
    let one = d
        .find(By::XPath("//div[@class='hxc3-hxc3KlinePricePane-hover']"))
        .await?;
    let six = d
        .find(By::XPath(
            "//div[@class='hxc3-hxc3KlinePricePane-hover-price']",
        ))
        .await?;

    let mut need_comp = true;
    if record.new_page == true {
        if record.prev_data == five.text().await? {
            println!("End all scrapy: {}", record.prev_data);
            return Ok(DataDone::EndAll);
        }
        record.old_prev_data = record.prev_data.clone();
        record.prev_data = five.text().await?;
        println!("new page, prev data: {}", record.prev_data);
        record.new_page = false;
        need_comp = false;
    }

    if five.text().await? == record.new_prev_data {
        return Ok(DataDone::No);
    }

    if need_comp {
        if record.old_prev_data == five.text().await? {
            println!("End current page scrapy: {}", record.prev_data);
            return Ok(DataDone::EndCurrent);
        }
    }

    record.new_prev_data = five.text().await?;
    let mut v = vec![];
    v.push(one.text().await?);
    v.push(two.text().await?);
    v.push(three.text().await?);
    v.push(four.text().await?);
    v.push(five.text().await?);
    v.push(six.text().await?);
    println!("{}", five.text().await?);
    Ok(DataDone::No)
}

#[tokio::main]
async fn async_main() -> WebDriverResult<()> {
    let mut caps = DesiredCapabilities::chrome();
    caps.set_headless()?;
    let driver = WebDriver::new("http://localhost:9515", caps).await?;

    // 切换到日 k 线
    driver
        .goto("http://stockpage.10jqka.com.cn/HQ_v4.html#hs_603266")
        .await?;
    let c = driver
        .find(By::XPath("//li/a[@hxc3-data-type='hxc3KlineQfqDay']"))
        .await?;
    driver.action_chain().click_element(&c).perform().await?;

    // 确保数据完全加载成功
    thread::sleep(Duration::from_secs(1));

    let mut record = ScrapyRecord::new(driver);

    // 循环爬取历史数据
    'end: loop {
        // 首先爬取当前页面的数据, 如果日期与之前爬取的重复,
        // 说明已经到了当前页面的最后一个数据, 拖拽新数据,
        // 直到拖拽后第一个数据就重复, 则爬取完所有数据.
        record.driver.action_chain().move_to(1, 100).perform().await?;
        record.new_page = true;
        let mut i = 1;

        while i < 618 {
            record.driver.action_chain().move_by_offset(5, 0).perform().await?;
            let res = handle_data(&mut record).await?;
            match res {
                DataDone::EndAll => break 'end,
                DataDone::EndCurrent => break,
                DataDone::No => {}
            }
            i += 5;
        }

        // 拖拽目标, 刷新数据
        let start = record.driver.find(By::XPath("//div[@id='testcanvas']")).await?;
        let end = record.driver.find(By::XPath("//div[@class='canvas-btn-box']")).await?;
        record.driver.action_chain().drag_and_drop_element(&start, &end).perform().await?;
    }

    record.driver.quit().await?;
    Ok(())
}

fn main() {
    async_main().unwrap();
}
